<?php
/**
 * appRain v 0.1.x
 *
 * LICENSE
 *
 * This source file is subject to the MIT license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://www.opensource.org/licenses/mit-license.php
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@apprain.com so we can send you a copy immediately.
 *
 * @copyright  Copyright (c) 2010 appRain, Team. (http://www.apprain.com)
 * @license    http://www.opensource.org/licenses/mit-license.php MIT license
 *
 * HELP
 *
 * Official Website
 * http://www.apprain.com/
 *
 * Download Link
 * http://www.apprain.com/download
 *
 * Documents Link
 * http ://www.apprain.com/docs
 */

abstract class appRain_Base_Modules_Validation extends appRain_Base_Objects
{
    /*
     *   Common Reguler Expression Rules
     */
    private $_ruleExp = Array(
                                'alphanumeric'  => '/^[\p{Ll}\p{Lm}\p{Lo}\p{Lt}\p{Lu}\p{Nd}]+$/mu',
                                'email'         => '/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$/i',
                                'password'      => '/^.*(?=.{8,})(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).*$/',
                                'notempty'      => '/.+/',
                                'time'          => '%^((0?[1-9]|1[012])(:[0-5]\d){0,2}([AP]M|[ap]m))$|^([01]\d|2[0-3])(:[0-5]\d){0,2}$%',
                                'cc'            => Array(   'amex' => '/^3[4|7]\\d{13}$/',
                                                            'bankcard' => '/^56(10\\d\\d|022[1-5])\\d{10}$/',
                                                            'diners'   => '/^(?:3(0[0-5]|[68]\\d)\\d{11})|(?:5[1-5]\\d{14})$/',
                                                            'disc'     => '/^(?:6011|650\\d)\\d{12}$/',
                                                            'electron' => '/^(?:417500|4917\\d{2}|4913\\d{2})\\d{10}$/',
                                                            'enroute'  => '/^2(?:014|149)\\d{11}$/',
                                                            'jcb'      => '/^(3\\d{4}|2100|1800)\\d{11}$/',
                                                            'maestro'  => '/^(?:5020|6\\d{3})\\d{12}$/',
                                                            'mc'       => '/^5[1-5]\\d{14}$/',
                                                            'solo'     => '/^(6334[5-9][0-9]|6767[0-9]{2})\\d{10}(\\d{2,3})?$/',
                                                            'switch'   => '/^(?:49(03(0[2-9]|3[5-9])|11(0[1-2]|7[4-9]|8[1-2])|36[0-9]{2})\\d{10}(\\d{2,3})?)|(?:564182\\d{10}(\\d{2,3})?)|(6(3(33[0-4][0-9])|759[0-9]{2})\\d{10}(\\d{2,3})?)$/',
                                                            'visa'     => '/^4\\d{12}(\\d{3})?$/',
                                                            'voyager'  => '/^8699[0-9]{11}$/'
                                                        )
                             );

	/**
	 * Validate Email Address
	 *
	 * @param $_value String
	 * @return Boolean
	 */
	public function email($_value)
    {
        return $this->setRuleType('email')
                    ->setRuleValue($_value)
                    ->excRegExp();

    }

    /**
	 * Validate Password
     * Rule: Password must be at least 8 characters and must contain at least one lower case letter, one upper case letter and one digit
	 *
	 * @param $_value String
	 * @return Boolean
	 */
	public function password($_value)
    {
        return $this->setRuleType('password')
                    ->setRuleValue($_value)
                    ->excRegExp();

    }

    public function textData($_value)
    {
        return true;
    }

    /**
     * In List
     */
    function inList($_value,$options)
    {
        if($this->allowEmpty($_value, $options))return true;

    	$list = isset($options["_list"])?$options["_list"]:$options;
		return in_array($_value, $list);
	}

	public function isImage($file_name = "",$options=Array())
    {
        if($this->allowEmpty($file_name, $options))return true;

        $list = isset($options["_list"])?$options["_list"]:$options;
    	$ext_arr =empty($list)?array('.gif','.jpg','.jpeg','.png'):$list;

        $sp = strrpos($file_name,'.');
        $ep = strlen($file_name);
        $ext = substr($file_name,$sp,$ep);
        return in_array(strtolower($ext),$ext_arr) ? true : false;
    }

	public function isDoc($file_name = "",$options=Array())
    {
        if($this->allowEmpty($file_name, $options))return true;

    	$list = isset($options["_list"])?$options["_list"]:$options;
    	$ext_arr =empty($list)?array('.doc','.docx','.txt','.docm','.docm','.rtf'):$list;

        $sp = strrpos($file_name,'.');
        $ep = strlen($file_name);
        $ext = substr($file_name,$sp,$ep);
        return in_array(strtolower($ext),$ext_arr) ? true : false;
    }

	public function isPDF($file_name = "",$options=Array())
    {
        if($this->allowEmpty($file_name, $options))return true;

        $list = isset($options["_list"])?$options["_list"]:$options;
    	$ext_arr =empty($list)?array('.pdf'):$list;

        $sp = strrpos($file_name,'.');
        $ep = strlen($file_name);
        $ext = substr($file_name,$sp,$ep);
        return in_array(strtolower($ext),$ext_arr) ? true : false;
    }

    public function notEmpty($_value="")
    {
        return $this->setRuleType('notempty')
                ->setRuleValue($_value)
                ->excRegExp();
	}

	private function allowEmpty($_value, $options)
	{
		$options["allowEmpty"] = isset($options["allowEmpty"])?$options["allowEmpty"]:"No";

		return (strtolower($options["allowEmpty"]) == "yes" && $_value=="")?true:false;
	}

    /**
	 * Validate Alpha Numeric Value
	 *
	 * @param $_value String
	 * @return Boolean
	 */
    public function alphaNumeric($_value)
    {

       return $this->setRuleType('alphanumeric')
                   ->setRuleValue($_value)
                   ->excRegExp();
	}

    /**
	 * Validate CC Value
	 *
	 * @param $_value String
	 * @return Boolean
	 */
    public function cc($_value,$options)
    {
        return $this->setReExp($this->_ruleExp['cc'][$options['type']])
		->setRuleValue($_value)
		->excRegExp();
    }

    public function uniqueInformation($_value,$options)
    {
	    $key = "findAllBy{$options['fieldname']}";
	    $info = App::InformationSet($options['type'])->$key($_value);
	    foreach($info['data'] as $key=>$val){if($val['id']==$options['id']){unset($info['data'][$key]);}}
	    return empty($info['data']);
    }

    public function unique($_value,$options)
    {
        $id  = isset($options['id']) ? $options['id'] : "";
        $fx = "findBy{$options['field']}";
        $row = App::Load("Model/{$options['model']}")->$fx($_value);

        if(empty($row)) return true;
        else return ($id==$row['id'])? true : false;
    }

    /**
     * Check Minimum lenght of a value
     */
    public function minlength($_value,$options)
    {
        return ($options['minlength'] > strlen($_value)) ? false : true;
    }

    /**
     * Check Minimum lenght of a value
     */
    public function maxlength($_value,$options)
    {
        return ($options['maxlength'] < strlen($_value)) ? false : true;
    }


    public function date($_value)
    {
        return (checkdate (
                        date('m',strtotime($_value)),
                        date('d',strtotime($_value)),
                        date('Y',strtotime($_value))));

    }

    public function time($_value)
    {

       return $this->setRuleType('time')
                   ->setRuleValue($_value)
                   ->excRegExp();
	}

    function boolean($_value) {
		$options = array(0, 1, '0', '1', true, false);
		return in_array($_value, $options, true);
	}

    function money($_value, $symbolPosition = 'left') {

		$exp = ($symbolPosition == 'right')
                ? '/^(?!0,?\d)(?:\d{1,3}(?:([, .])\d{3})?(?:\1\d{3})*|(?:\d+))((?!\1)[,.]\d{2})?(?<!\x{00a2})\p{Sc}?$/u'
			    : '/^(?!\x{00a2})\p{Sc}?(?!0,?\d)(?:\d{1,3}(?:([, .])\d{3})?(?:\1\d{3})*|(?:\d+))((?!\1)[,.]\d{2})?$/u';

        return $this->setReExp($exp)
                    ->setRuleValue($_value)
                    ->excRegExp();
	}

    function isNumber( $_value, $optins)
    {
        return is_numeric($_value);
    }


    /**
     * Execute Validation By Reguler Expression
     */
    public function excRegExp()
    {
        if($this->getReExp())
        {
            $exp = $this->getReExp();
            $this->unsetReExp();
        }
        else
        {
            $exp = $this->_ruleExp[$this->getRuleType()];
        }

        return preg_match($exp,$this->getRuleValue());
    }
}